home *** CD-ROM | disk | FTP | other *** search
-
- //Copyright 1991-1992 Roger Bedell All rights reserved
- //See the attached readme file for licensing information.
-
- #include "time.h"
- #include "stdlib.h"
- #include "stdio.h"
- #include "string.h"
- #include "io.h"
- #include "grafprnt.hpp"
- #include "graffile.hpp"
- #include "mem.h"
-
- //global printer error flag set to 1 on a printer error
- extern int printer_error_flag;
-
- void * graphics_printer::allocate_graphics_printer(int pixels_per_line)
- {
- void *printer_ptr;
- //figure out which kind of printer to create
- switch(printer_type)
- {
- case 1:
- printer_ptr = new epson_24_graphics_printer(pixels_per_line);
- break;
- case 2:
- printer_ptr = new hp_laser_graphics_printer(pixels_per_line);
- break;
- }
- return printer_ptr;
-
- }
-
-
- void graphics_printer::line_feed()
- {
- char feed[3] = {0x0a,0x0d};
- send_print_buffer(feed,2);
- }
-
- extern int bbprinter_number;
- int send_cmd( char *line_buffer, int length );
- int opn_prt(char * path ,int i);
- int cls_prt(int flag);
- int flush_buf(void);
-
-
- void epson_24_graphics_printer::open_graphics_printer()
- {
- port_handle = 4; //prn device
-
- bbprinter_number = 0;
- opn_prt("lpt1", 0);
-
- //send it the appropriate string for turn on
- char turn_on_string[6]={0x1b,0x40,0x1b,0x33,0x18};
-
- send_print_buffer(turn_on_string, 5);
-
-
- }
- void hp_laser_graphics_printer::open_graphics_printer()
- {
- port_handle = 4; //prn device
-
- bbprinter_number = 0;
- opn_prt("lpt1", 0);
-
- //set it to 300 dpi and prepare for graphics
- send_print_buffer("\x1b*t300R", strlen("\x1b*t300R"));
- send_print_buffer("\x1b*r0A", strlen("\x1b*r0A"));
-
-
- }
-
-
-
-
- void epson_24_graphics_printer::close_graphics_printer()
- {
- //send it the appropriate string for turn on
- char turn_off_string[6]={0xC};
-
- send_print_buffer(turn_off_string, 1);
-
- }
-
- void hp_laser_graphics_printer::close_graphics_printer()
- {
- //send it the appropriate string for turn off
- send_print_buffer("\x1b*rB", strlen("\x1b*rB"));
- send_print_buffer("\x0c", strlen("\x0c"));
-
- }
-
- void graphics_printer::send_print_buffer(char * line_buffer, int length)
- {
- send_cmd(line_buffer, length);
- }
-
- void epson_24_graphics_printer::send_graphics_buffer(char * line_buffer, int length)
- {
-
- //for an epson, the width is in dot columns
- //in this case three bytes for each column
- int temp = length / 3;
-
- char n1 = temp % 256;
- char n2 = temp / 256;
-
- //send the epson prelude to a graphics line
- char turn_on_graphics_string[6]={0x1B,0x2A,0x27};
- turn_on_graphics_string[3]=n1;
- turn_on_graphics_string[4]=n2;
- send_print_buffer(turn_on_graphics_string, 5);
-
- send_print_buffer(line_buffer, length);
-
- //do a line feed
- char turn_off_graphics_string[6]={0xD,0xA};
- send_print_buffer(turn_off_graphics_string, 2);
-
- }
-
-
- void hp_laser_graphics_printer::send_graphics_buffer(unsigned char * line_buffer, int length)
- {
-
- //for an HP, the width is in dot columns
- //in this case three bytes for each column
-
- //send the hp prelude to a graphics line
- char turn_on_graphics[20];
- sprintf(turn_on_graphics,"\x1b*b%dW", length);
-
- send_print_buffer(turn_on_graphics, strlen(turn_on_graphics));
-
- //send the data itself. no line feed is necessary
- send_print_buffer((char *)line_buffer, length);
-
- }
-
-
-
-
- //this is the entry to the printer from the graphics file object
- //a generic grey scaled line is passed to this method. The
- //printer object will then dither and print this line according
- //to the scaling factors required for the printer resolution and
- //page size.
-
- void graphics_printer::print_grey_line(char * buffer, int buffer_length)
- {
- //Set the object variables
- grey_line_buffer = buffer;
- grey_line_count = buffer_length;
-
- expand_grey_line();
-
- //send the expanded grey info to the ditherer a line at a time,
- //then convert
- //the dithered line to a line of bits, then send the line of bits
- //to the printer
- int i;
- for(i = 0; i < expansion_factor_y; i++)
- {
- //send a line to the ditherer, it will produce a dithered line
- dither_expanded_line(i);
-
- //send the line to the bits converter, produces a bits line
- convert_dithered_line_to_bits();
-
- //send the bits line to the printer
- bits_to_printer();
-
- }
-
-
- }
-
-
- //constructor
- //pass it the width of the pcx graphic so it can allocae buffers
- epson_24_graphics_printer::epson_24_graphics_printer(int pixels_per_line)
- {
-
- //set the expansion factors
- expansion_factor_x = 2;
- expansion_factor_y = 2;
-
- //init pin counter counts from 0 to 23 pins on this 24 pin ptr
- pin_number = 0;
-
- //and the length of each line
- len_expanded_lines = expansion_factor_x * pixels_per_line;
-
- //allocate memory for the various buffers
- //allocate memory for the expansion buffer
- for( int j = 0; j < expansion_factor_y; j++)
- {
- expansion_buffer[j] = mem_malloc(len_expanded_lines);
- if(expansion_buffer[j] ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
- }
-
- //and for the dither buffer
- for( j = 0; j < 2; j++)
- {
- dither_buffer[j] = mem_malloc(len_expanded_lines + 10);
-
- if(dither_buffer[j] ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
-
- //set the dither buffer to all 129s so it will be white with
- //very little error in the first line
- memset(dither_buffer[j], 255, len_expanded_lines);
- }
-
- completed_dither_buffer = mem_malloc(len_expanded_lines);
-
- if(completed_dither_buffer ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
- bits_buffer = mem_malloc(((len_expanded_lines) / 8) + 1);
- if(bits_buffer ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
-
- //and for the printer buffer itself.
- printer_buffer = mem_malloc(len_expanded_lines * 3);
- if(printer_buffer ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
- //clear it
- memset(printer_buffer, 0, len_expanded_lines * 3);
-
- open_graphics_printer();
-
- }
-
- //destructor
- void epson_24_graphics_printer::deallocate_graphics_printer(void)
- {
- int j;
-
- //deallocate the memory for the buffers
- for( j = 0; j < expansion_factor_y; j++)
- {
- mem_free(expansion_buffer[j]);
- }
-
-
- //deallocate the memory for the buffers
- for( j = 0; j < 2; j++)
- {
- mem_free(dither_buffer[j]);
- }
- mem_free(completed_dither_buffer);
- mem_free(bits_buffer);
-
- mem_free(printer_buffer);
-
- close_graphics_printer();
- }
-
- //constructor
- //pass it the width of the pcx graphic so it can allocae buffers
- hp_laser_graphics_printer::hp_laser_graphics_printer(int pixels_per_line)
- {
-
- //set the expansion factors
- expansion_factor_x = 3;
- expansion_factor_y = 3;
-
- //and the length of each line
- len_expanded_lines = expansion_factor_x * pixels_per_line;
-
- //allocate memory for the various buffers
- //allocate memory for the expansion buffer
- for( int j = 0; j < expansion_factor_y; j++)
- {
- expansion_buffer[j] = mem_malloc(pixels_per_line * expansion_factor_x);
- if(expansion_buffer[j] ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
- }
-
- //and for the dither buffer
- for( j = 0; j < 2; j++)
- {
- dither_buffer[j] = mem_malloc(pixels_per_line * expansion_factor_x + 10);
- if(dither_buffer[j] ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
-
- //set the dither buffer to all 129s so it will be white with
- //very little error in the first line
- memset(dither_buffer[j], 255, len_expanded_lines);
- }
-
- completed_dither_buffer = mem_malloc(len_expanded_lines);
- if(completed_dither_buffer == NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
-
- //and for the bits buffer. no printer buffer is needed
- //as this is the final step
- bits_buffer = mem_malloc(((len_expanded_lines) / 8) + 1);
- if(bits_buffer ==NULL)
- {
- error_message("Not enough memory for print buffer.",NONFATAL);
- deallocate_graphics_printer();
- return;
- }
-
- open_graphics_printer();
-
- }
-
- //destructor
- void hp_laser_graphics_printer::deallocate_graphics_printer(void)
- {
- int j;
-
- //deallocate the memory for the buffers
- for( j = 0; j < expansion_factor_y; j++)
- {
- mem_free(expansion_buffer[j]);
- }
- //deallocate the memory for the buffers
- for( j = 0; j < 2; j++)
- {
- mem_free(dither_buffer[j]);
- }
- mem_free(completed_dither_buffer);
- mem_free(bits_buffer);
-
- close_graphics_printer();
- }
-
- //generic grey line expander. Given the x and y expansion
- //factors, we can expand the grey line into the expand buffer
- void graphics_printer::expand_grey_line()
- {
- //currently we can only handle integral expansion factors
- int i,j,k;
-
-
- //for each and every byte in the grey line...
- for( i = 0; i < grey_line_count; i++)
- {
- //expand the number of times specified in the y direction
- for( j = 0; j < expansion_factor_y; j++)
- {
- //expand the number of times specified in the x direction
- for( k = 0; k < expansion_factor_x; k++)
- {
- expansion_buffer[j][(i * expansion_factor_x) + k] =
- grey_line_buffer[i];
- }
- }
-
- }
-
- }
-
- void graphics_printer::dither_expanded_line(int line_number)
- {
- //takes the specified expanded line and puts it into the
- //bottom of the dither buffer. Then runs the Floyd Steinberg
- //dither algorithm on the three lines in the buffer. When
- //done, takes the top line and copies it into the completed
- //dithered line buffer.
-
- //copy the second line into the first
- memcpy(dither_buffer[0], dither_buffer[1], len_expanded_lines);
-
- //and the new one into the second
- memcpy(dither_buffer[1], expansion_buffer[line_number], len_expanded_lines);
-
- int error;
- //apply Floyd Steinberg dither to the dither buffer
- //go along the top row and diffuse the errors that are seen
- //however, do a serpentine scan. Dither from the left
- //to right one time, then right to left the next time
-
-
- if(serpentine == 0)
- { //left to right
- serpentine = 1;
- for( int i = 1; i < len_expanded_lines - 2; i++)
- {
- if(dither_buffer[0][i] > 128) //it will be white
- {
- //calculate the error (since its not quite white)
- error = dither_buffer[0][i] - 255;
- }
- else //it will be a black dot
- {
- //calculate the error (since its not quite black)
- error = dither_buffer[0][i];
- }
-
- //Now distribute the error.
- //see Rimmer P.391
- dither_buffer[0][i + 1] += (7 * error) / 16;
- dither_buffer[1][i - 1] += (3 * error) / 16;
- dither_buffer[1][i] += (5 * error) / 16;
- dither_buffer[1][i + 1] += (1 * error) / 16;
-
- }
- }
- else //dither right to left
- {
- serpentine = 0;
- for( int i = len_expanded_lines; i > 2; i--)
- {
- if(dither_buffer[0][i] > 128) //it will be white
- {
- //calculate the error (since its not quite white)
- error = dither_buffer[0][i] - 255;
- }
- else //it will be a black dot
- {
- //calculate the error (since its not quite black)
- error = dither_buffer[0][i];
- }
-
- //Now distribute the error.
- //see Rimmer P.391
- dither_buffer[0][i + 1] += (7 * error) / 16;
- dither_buffer[1][i - 1] += (3 * error) / 16;
- dither_buffer[1][i] += (5 * error) / 16;
- dither_buffer[1][i + 1] += (1 * error) / 16;
-
- }
-
-
- }
-
- //Copy the completed first line to the completed dither buffer
- memcpy(completed_dither_buffer, dither_buffer[0], len_expanded_lines);
-
-
- }
-
- void graphics_printer::convert_dithered_line_to_bits(void)
- {
- //takes the dithered line buffer and converts it to
- //a single line of bits using a threshold of 128
-
- char set_byte;
-
- //clear the bits buffer to all zeros
- memset(bits_buffer, 0 , (len_expanded_lines / 8)+1);
-
- for( int i = 0; i < len_expanded_lines; i++)
- {
- if(completed_dither_buffer[i] > 128)
- {
- //its white, so dont print it (0)
- //(nothing needs to be done)
- }
- else //its black, so print it (1)
- {
- set_byte = 1; //start with one
-
- set_byte = set_byte << (i % 8); //left shift to get it in the right spot
-
- bits_buffer[i / 8] |= set_byte; //Or it to set the right bit
- }
- }
-
-
- }
-
- void graphics_printer::bits_to_printer(void)
- {
- //takes the line of bits and sends it to the printer. If its
- //a dot matrix, this is a little more complicated, but
- //eventually the printer prints out a line made of these bits.
- //laser printers are really easy!
- }
-
- void epson_24_graphics_printer::bits_to_printer(void)
- {
- //takes the line of bits and sends it to the printer.
- //In this case, the orientation of the pins on the printer
- //and how they are addressed assume primary proportion
- //In a 24 pin printer, there are three bytes for each
- //24 pin impact. What we will do is set the bits for
- //the top pin all the way across the paper, then the
- //second pin the next time this routine is called etc.
- //when we've done this 24 times, we ship the whole thing
- //out to the printer.
-
- //we're dealing with the same pin all the way across the swath
- int pin_row_byte = pin_number / 8;
- int pin_row_bit = pin_number % 8;
- //Top pin is the MSBit
- unsigned char pin_row_set_bit = 0x80 >> pin_row_bit;
-
- for( int i = 0; i < len_expanded_lines; i++)
- {
- //see if the ith bit is 1 or 0 and
- //set the corresponding bit in the printer buffer
- unsigned char set_byte = 0x01; //start with one
-
- set_byte = set_byte << (i % 8); //left shift to get it in the right spot
-
- //Note that the least significant bit in the
- //3 byte word controls the bottom pin, the most
- //significant bit controls the top pin
- if(bits_buffer[i / 8] & set_byte) //set or not?
- {
- //its a one!
- //so set the pin in the swath . This is the final step
- //before printing
- printer_buffer[( i * 3 ) + pin_row_byte ] |= pin_row_set_bit;
- }
- else
- {//do nothing
- }
-
- }
-
- if(++pin_number >= 24)
- {
- //print the swath
- send_graphics_buffer(printer_buffer,len_expanded_lines * 3);
- // printf("Swath printed.\n");
-
- //clear out the printer buffer
- memset(printer_buffer, 0, len_expanded_lines * 3);
-
- //reset the pin counter
- pin_number = 0;
- }
-
-
- }
-
-
- void reverse_bytes_in_buffer(unsigned char *buffer, int len);
-
- void hp_laser_graphics_printer::bits_to_printer(void)
- {
- //takes the line of bits and sends it to the printer.
- //In this case, the orientation of the pins on the printer
- //and how they are addressed assume primary proportion
- //In a laser printer, there is one bit for each dot
-
- //just ship them out the way they are in the dot buffer
-
- //reverse the bytes, then ship them out
- reverse_bytes_in_buffer(bits_buffer, len_expanded_lines / 8);
- send_graphics_buffer(bits_buffer, len_expanded_lines / 8);
-
- }
-
- //for each byte in the buffer, reverse the bit order
- void reverse_bytes_in_buffer(unsigned char *buffer, int len)
- {
- //for each byte in the buffer, reverse the bit order
- for(int i = 0; i < len; i ++)
- {
- char temp_char = buffer[i];
- char temp_char2 = 0;
-
- for (int j=0; j < 8; j++)
- {
- temp_char2 = temp_char2 << 1;
-
- if(temp_char & 1 == 1)
- {
- //or a one to the the end result
- temp_char2 |= 1;
- }
- //left shift the end result and right shift the temp
- temp_char = temp_char >> 1;
-
- }
- buffer[i] = temp_char2;
- }
-
- }
-
-
-